using System.Security.Cryptography;
using System.Text;
using System.IO;
using Microsoft.Win32;

namespace LicenseApp.Client;

/// <summary>
/// 简洁的时间防护器 - 防止时间回拨作弊 + 多重防删除保护
/// </summary>
public static class SimpleTimeGuard
{
    // 应用程序路径获取 - 按要求实现
    private static readonly string assemblyFilePath = System.Diagnostics.Process.GetCurrentProcess().MainModule?.FileName ?? "";
    private static readonly string assemblyDirPath = System.IO.Path.GetDirectoryName(assemblyFilePath) ?? "";

    // 注册表存储（使用自定义后缀，确保不与系统设置冲突）
    private const string REGISTRY_KEY = @"HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced";
    private const string REGISTRY_VALUE = "NavPaneExpandToCurrentFolder_ZhyLsHK"; // 自定义后缀，确保唯一

    // 🎯 简化为两种协防：应用目录文件 + 注册表
    private static readonly string[] TimeStampFiles = new[]
    {
        // 程序目录（主要存储位置）
        System.IO.Path.Combine(assemblyDirPath, ".sys_cache.tmp"),

        // 程序目录备份（协防位置）
        System.IO.Path.Combine(assemblyDirPath, ".timestamp_backup.tmp")
    };

    // 简单的加密密钥
    private static readonly byte[] EncryptionKey = Encoding.UTF8.GetBytes("LicenseApp2025Key!@#");

    /// <summary>
    /// 验证时间合法性并更新时间戳
    /// </summary>
    /// <returns>验证结果</returns>
    public static TimeValidationResult ValidateAndUpdateTime()
    {
        try
        {
            var currentTime = DateTime.Now;
            var lastRunTime = GetLastRunTime();

            var result = new TimeValidationResult
            {
                CurrentTime = currentTime,
                LastRunTime = lastRunTime,
                IsValid = true
            };

            // 如果是首次运行（没有记录）
            if (lastRunTime == DateTime.MinValue)
            {
                result.IsFirstRun = true;
                result.Message = "首次运行，初始化时间记录";
                SaveLastRunTime(currentTime);
                return result;
            }

            // 检查时间回拨（允许5分钟的误差，考虑时间同步）
            var timeDifference = currentTime - lastRunTime;
            if (timeDifference.TotalMinutes < -5)
            {
                result.IsValid = false;
                result.IsTimeRollback = true;
                result.Message = $"检测到系统时间回拨 {Math.Abs(timeDifference.TotalHours):F1} 小时，可能存在非法操作";
                return result;
            }

            // 检查时间跳跃过大（超过7天，可能是恶意修改）
            if (timeDifference.TotalDays > 7)
            {
                result.IsValid = false;
                result.IsTimeJump = true;
                result.Message = $"检测到系统时间异常跳跃 {timeDifference.TotalDays:F1} 天，请检查系统时间";
                return result;
            }

            // 正常情况，更新时间戳
            result.Message = "时间验证通过";
            SaveLastRunTime(currentTime);
            return result;
        }
        catch (Exception ex)
        {
            return new TimeValidationResult
            {
                IsValid = false,
                Message = $"时间验证失败: {ex.Message}",
                CurrentTime = DateTime.Now
            };
        }
    }

    /// <summary>
    /// 计算基于授权的实际使用天数
    /// </summary>
    /// <param name="licenseStartDate">授权生效日期</param>
    /// <param name="currentDate">当前日期</param>
    /// <returns>使用天数</returns>
    public static int CalculateUsedDays(DateTime licenseStartDate, DateTime? currentDate = null)
    {
        var today = (currentDate ?? DateTime.Now).Date;
        var startDate = licenseStartDate.Date;

        // 如果当前日期早于生效日期，使用天数为0
        if (today < startDate)
        {
            return 0;
        }

        // 计算从生效日期到当前日期的天数（包含当天）
        var usedDays = (int)(today - startDate).TotalDays + 1;
        return Math.Max(1, usedDays);
    }

    /// <summary>
    /// 获取上次运行时间（从多个存储位置）
    /// </summary>
    private static DateTime GetLastRunTime()
    {
        var timestamps = new List<DateTime>();

        // 1. 从文件存储加载
        foreach (var filePath in TimeStampFiles)
        {
            var timestamp = LoadTimeFromFile(filePath);
            if (timestamp != DateTime.MinValue)
            {
                timestamps.Add(timestamp);
            }
        }

        // 2. 从注册表加载
        var registryTimestamp = LoadTimeFromRegistry();
        if (registryTimestamp != DateTime.MinValue)
        {
            timestamps.Add(registryTimestamp);
        }

        // 3. 选择最新的时间戳（防止用户通过删除部分文件来"回退"时间）
        return timestamps.Count > 0 ? timestamps.Max() : DateTime.MinValue;
    }

    /// <summary>
    /// 从文件加载时间戳
    /// </summary>
    private static DateTime LoadTimeFromFile(string filePath)
    {
        try
        {
            if (!System.IO.File.Exists(filePath))
                return DateTime.MinValue;

            var encryptedData = System.IO.File.ReadAllBytes(filePath);
            var decryptedData = SimpleDecrypt(encryptedData);
            var timeString = Encoding.UTF8.GetString(decryptedData);

            if (DateTime.TryParse(timeString, out var lastTime))
                return lastTime;

            return DateTime.MinValue;
        }
        catch
        {
            return DateTime.MinValue;
        }
    }

    /// <summary>
    /// 从注册表加载时间戳
    /// </summary>
    private static DateTime LoadTimeFromRegistry()
    {
        try
        {
            var value = Registry.GetValue(REGISTRY_KEY, REGISTRY_VALUE, null);
            if (value is int intValue && intValue != 0) // 0是系统默认值，忽略
            {
                return DecodeTimestamp(intValue);
            }
            return DateTime.MinValue;
        }
        catch
        {
            return DateTime.MinValue;
        }
    }

    /// <summary>
    /// 保存当前运行时间（到所有存储位置）
    /// </summary>
    private static void SaveLastRunTime(DateTime currentTime)
    {
        // 保存到文件存储
        SaveTimeToFiles(currentTime);

        // 保存到注册表
        SaveTimeToRegistry(currentTime);
    }

    /// <summary>
    /// 保存时间戳到文件存储
    /// </summary>
    private static void SaveTimeToFiles(DateTime currentTime)
    {
        var timeString = currentTime.ToString("yyyy-MM-dd HH:mm:ss");
        var data = Encoding.UTF8.GetBytes(timeString);
        var encryptedData = SimpleEncrypt(data);

        foreach (var filePath in TimeStampFiles)
        {
            try
            {
                // 🛠️ 修复：增强的目录创建和权限检查
                var directory = System.IO.Path.GetDirectoryName(filePath);
                if (!string.IsNullOrEmpty(directory))
                {
                    if (!Directory.Exists(directory))
                    {
                        try
                        {
                            Directory.CreateDirectory(directory);
                        }
                        catch (UnauthorizedAccessException)
                        {
                            // 权限不足，跳过这个路径
                            continue;
                        }
                        catch
                        {
                            // 其他错误，跳过这个路径
                            continue;
                        }
                    }
                }

                // 🛠️ 修复：检查文件写入权限
                try
                {
                    System.IO.File.WriteAllBytes(filePath, encryptedData);
                }
                catch (UnauthorizedAccessException)
                {
                    // 权限不足，跳过这个路径
                    continue;
                }

                // 🛠️ 修复：移除隐藏属性设置，避免文件访问问题
            }
            catch
            {
                // 单个文件保存失败不影响其他文件
            }
        }
    }

    /// <summary>
    /// 保存时间戳到注册表
    /// </summary>
    private static void SaveTimeToRegistry(DateTime currentTime)
    {
        try
        {
            var encodedValue = EncodeTimestamp(currentTime);
            Registry.SetValue(REGISTRY_KEY, REGISTRY_VALUE, encodedValue, RegistryValueKind.DWord);
        }
        catch
        {
            // 注册表保存失败不影响主要功能
        }
    }

    /// <summary>
    /// 简单加密
    /// </summary>
    private static byte[] SimpleEncrypt(byte[] data)
    {
        try
        {
            using var aes = Aes.Create();
            aes.Key = PadKey(EncryptionKey);
            aes.GenerateIV();

            using var encryptor = aes.CreateEncryptor();
            var encrypted = encryptor.TransformFinalBlock(data, 0, data.Length);

            // 将IV和加密数据合并
            var result = new byte[aes.IV.Length + encrypted.Length];
            Array.Copy(aes.IV, 0, result, 0, aes.IV.Length);
            Array.Copy(encrypted, 0, result, aes.IV.Length, encrypted.Length);

            return result;
        }
        catch
        {
            // 加密失败，返回简单混淆的数据
            return SimpleObfuscate(data);
        }
    }

    /// <summary>
    /// 简单解密
    /// </summary>
    private static byte[] SimpleDecrypt(byte[] encryptedData)
    {
        try
        {
            using var aes = Aes.Create();
            aes.Key = PadKey(EncryptionKey);

            // 提取IV
            var iv = new byte[16];
            Array.Copy(encryptedData, 0, iv, 0, 16);
            aes.IV = iv;

            // 提取加密数据
            var encrypted = new byte[encryptedData.Length - 16];
            Array.Copy(encryptedData, 16, encrypted, 0, encrypted.Length);

            using var decryptor = aes.CreateDecryptor();
            return decryptor.TransformFinalBlock(encrypted, 0, encrypted.Length);
        }
        catch
        {
            // 解密失败，尝试简单反混淆
            return SimpleDeobfuscate(encryptedData);
        }
    }

    /// <summary>
    /// 填充密钥到32字节
    /// </summary>
    private static byte[] PadKey(byte[] key)
    {
        var paddedKey = new byte[32];
        for (int i = 0; i < paddedKey.Length; i++)
        {
            paddedKey[i] = key[i % key.Length];
        }
        return paddedKey;
    }

    /// <summary>
    /// 简单混淆（备用方案）
    /// </summary>
    private static byte[] SimpleObfuscate(byte[] data)
    {
        var result = new byte[data.Length];
        for (int i = 0; i < data.Length; i++)
        {
            result[i] = (byte)(data[i] ^ 0xAA ^ (i % 256));
        }
        return result;
    }

    /// <summary>
    /// 简单反混淆（备用方案）
    /// </summary>
    private static byte[] SimpleDeobfuscate(byte[] data)
    {
        return SimpleObfuscate(data); // XOR是对称的
    }

    /// <summary>
    /// 将时间戳编码为整数（用于注册表存储）
    /// </summary>
    private static int EncodeTimestamp(DateTime timestamp)
    {
        try
        {
            // 编码格式：年份后两位(7位) + 月份(4位) + 日期(5位) + 小时(5位) + 分钟(6位) + 校验位(5位)
            var year = timestamp.Year % 100;
            var month = timestamp.Month;
            var day = timestamp.Day;
            var hour = timestamp.Hour;
            var minute = timestamp.Minute;
            var checksum = (year + month + day + hour + minute) % 32;

            return (year << 25) | (month << 21) | (day << 16) | (hour << 11) | (minute << 5) | checksum;
        }
        catch
        {
            return 0;
        }
    }

    /// <summary>
    /// 从整数解码时间戳
    /// </summary>
    private static DateTime DecodeTimestamp(int encodedValue)
    {
        try
        {
            var year = ((encodedValue >> 25) & 0x7F) + 2000;
            var month = (encodedValue >> 21) & 0x0F;
            var day = (encodedValue >> 16) & 0x1F;
            var hour = (encodedValue >> 11) & 0x1F;
            var minute = (encodedValue >> 5) & 0x3F;
            var checksum = encodedValue & 0x1F;

            // 验证校验和
            if (((year % 100) + month + day + hour + minute) % 32 != checksum)
            {
                return DateTime.MinValue;
            }

            // 验证日期有效性
            if (month < 1 || month > 12 || day < 1 || day > 31 || hour > 23 || minute > 59)
            {
                return DateTime.MinValue;
            }

            return new DateTime(year, month, day, hour, minute, 0);
        }
        catch
        {
            return DateTime.MinValue;
        }
    }
}

/// <summary>
/// 时间验证结果
/// </summary>
public class TimeValidationResult
{
    public bool IsValid { get; set; }
    public bool IsFirstRun { get; set; }
    public bool IsTimeRollback { get; set; }
    public bool IsTimeJump { get; set; }
    public DateTime CurrentTime { get; set; }
    public DateTime LastRunTime { get; set; }
    public string Message { get; set; } = "";
}
